package goutl

import (
	"gitee.com/xiakai001/goutl/constraints"
	"math/rand"
	"sort"
)

func ArrContains[V comparable](arr []V, v V) bool {

	for _, a := range arr {
		if a == v {
			return true
		}
	}

	return false
}

func ArrNotContains[V comparable](arr []V, v V) bool {

	return !ArrContains(arr, v)
}

// DistinctArr 数组去重
func DistinctArr[V comparable](arr ...[]V) []V {
	if len(arr) == 0 {
		return []V{}
	}
	existMap := make(map[V]struct{}, len(arr[0]))
	resArr := make([]V, 0, len(arr[0]))
	for _, _arr := range arr {
		for _, a := range _arr {
			_, ok := existMap[a]
			if !ok {
				existMap[a] = exist
				resArr = append(resArr, a)
			}
		}
	}

	return resArr
}

// DistinctCustomArr 数组去重，自定义去重key
func DistinctCustomArr[V any, C comparable](keyFn func(V) C, arr ...[]V) []V {
	if len(arr) == 0 {
		return []V{}
	}
	existMap := make(map[C]struct{}, len(arr[0]))
	resArr := make([]V, 0, len(arr[0]))
	for _, _arr := range arr {
		for _, a := range _arr {
			c := keyFn(a)
			_, ok := existMap[c]
			if !ok {
				existMap[c] = exist
				resArr = append(resArr, a)
			}
		}
	}

	return resArr
}

// FilterArr 数组过滤，filterFn为true则保存到输出数组，false则过滤
func FilterArr[V any](filterFn func(V) bool, arr ...[]V) []V {
	if len(arr) == 0 {
		return []V{}
	}

	resArr := make([]V, 0, len(arr[0]))
	for _, _arr := range arr {
		for _, a := range _arr {
			if filterFn(a) {
				resArr = append(resArr, a)
			}
		}
	}

	return resArr
}

// ShuffleArr 数组随机
func ShuffleArr[V any](arr []V) []V {
	if len(arr) == 0 {
		return arr
	}

	rand.Shuffle(len(arr), func(i, j int) {
		arr[i], arr[j] = arr[j], arr[i]
	})

	return arr
}

func ParseArrToArr[V any, E any](arr []V, parse func(V) E) []E {

	res := make([]E, 0, len(arr))
	for _, a := range arr {
		res = append(res, parse(a))
	}

	return res
}

// ParseMapKeyToArr 提取map key为数组
func ParseMapKeyToArr[K comparable, V any](m map[K]V) []K {

	res := make([]K, 0, len(m))
	for k := range m {
		res = append(res, k)
	}

	return res
}

// ParseCustomMapKeyToArr 提取map key为数组
func ParseCustomMapKeyToArr[K comparable, V any, E any](m map[K]V, parse func(K) E) []E {

	res := make([]E, 0, len(m))
	for k := range m {
		if parse == nil {
			res = append(res, interface{}(k).(E))
		} else {
			res = append(res, parse(k))
		}

	}

	return res
}

// ParseMapValueToArr 提取map value为数组
func ParseMapValueToArr[K comparable, V any](m map[K]V) []V {

	res := make([]V, 0, len(m))
	for _, v := range m {
		res = append(res, v)
	}

	return res
}

// ParseCustomMapValueToArr 提取map value为数组
func ParseCustomMapValueToArr[K comparable, V any, E any](m map[K]V, parse func(V) E) []E {

	res := make([]E, 0, len(m))
	for _, v := range m {
		if parse == nil {
			res = append(res, interface{}(v).(E))
		} else {
			res = append(res, parse(v))
		}
	}

	return res
}

// ReverseArr 翻转数组
func ReverseArr[T any](arr []T) {
	l := len(arr)
	for i := 0; i < l>>1; i++ {
		Swap(arr, i, l-i-1)
	}
}

func CompareArr[T constraints.Ordered](arrA, arrB []T) int {

	index := 0
	for index < len(arrA) && index < len(arrB) {
		if arrA[index] < arrB[index] {
			return -1
		}
		if arrA[index] > arrB[index] {
			return 1
		}
		index++
	}

	if index < len(arrA) {
		return 1
	}
	if index < len(arrB) {
		return -1
	}

	return 0
}

func SortAsc[T constraints.Ordered](arr []T) {
	Sort(arr, func(a, b T) bool { return a < b })
}

func SortDesc[T constraints.Ordered](arr []T) {
	Sort(arr, func(a, b T) bool { return a > b })
}

type sortStruct[K any] struct {
	arr     []K
	compare func(K, K) bool
}

func (s *sortStruct[K]) Len() int {
	return len(s.arr)
}

func (s *sortStruct[K]) Less(i, j int) bool {
	return s.compare(s.arr[i], s.arr[j])
}

func (s *sortStruct[K]) Swap(i, j int) {
	s.arr[i], s.arr[j] = s.arr[j], s.arr[i]
}

func Sort[T any](arr []T, compare func(a, b T) bool) {
	sort.Sort(&sortStruct[T]{
		arr:     arr,
		compare: compare,
	})
}

func Swap[T any](arr []T, i, j int) {
	arr[i], arr[j] = arr[j], arr[i]
}
